package cn.cloudtogo.support.mysql.column;

import cn.cloudtogo.common.Assert;
import org.springframework.util.StringUtils;

import java.util.Objects;

/**
 * @author yaolianhua789@gmail.com
 **/
public final class AlterColumnBuilder {
    private AlterColumnBuilder() {
    }

    public static String modifyColumnDefinitionSql(ColumnDefinition column, String schema, String table) {

        Assert.argument(StringUtils.hasText(column.getName()), () -> "column name is null");
        Assert.notNull(column.getTypes(), () -> "types is null");

        Types.ColumnType type = column.getTypes().getColumnType();
        String datatype;
        if (Types.ColumnType.VARCHAR.equals(type)) {
            datatype = String.format("VARCHAR(%s)", StringUtils.hasText(column.getTypes().getLength()) ? column.getTypes().getLength() : 500);
        } else {
            datatype = column.getTypes().getColumnType().name();
        }
        StringBuilder builder = new StringBuilder();
        builder.append(String.format("alter table `%s`.`%s` modify `%s` %s ", schema, table, column.getName(), datatype));

        if (column.isNotNull()) {
            builder.append("not null ");
        } else {
            builder.append("null ");
        }

        if (StringUtils.hasText(column.getDefaultValue())) {
            builder.append(String.format("default %s ", column.getDefaultValue()));
        }
        builder.append(String.format("comment '%s'", column.getComment()));

        return builder.toString();
    }

    public static String modifyColumnNameSql(ColumnDefinition column, String schema, String table, String newColumnName) {

        Assert.argument(StringUtils.hasText(column.getName()), () -> "origin column name is null");
        Assert.argument(StringUtils.hasText(newColumnName), () -> "new column name is null");
        Assert.notNull(column.getTypes(), () -> "types is null");

        Types.ColumnType type = column.getTypes().getColumnType();
        String datatype;
        if (Types.ColumnType.VARCHAR.equals(type)) {
            datatype = String.format("VARCHAR(%s)", StringUtils.hasText(column.getTypes().getLength()) ? column.getTypes().getLength() : 500);
        } else {
            datatype = column.getTypes().getColumnType().name();
        }
        StringBuilder builder = new StringBuilder();
        builder.append(String.format("alter table `%s`.`%s` change `%s` `%s` %s ", schema, table, column.getName(), newColumnName, datatype));

        if (column.isNotNull()) {
            builder.append("not null ");
        } else {
            builder.append("null ");
        }

        if (StringUtils.hasText(column.getDefaultValue())) {
            builder.append(String.format("default '%s' ", column.getDefaultValue()));
        }
        builder.append(String.format("comment '%s'", column.getComment()));

        return builder.toString();
    }

    public static String dropColumnSql(String schema, String table, String column) {

        Assert.argument(StringUtils.hasText(column), () -> "column name is null");
        String sql = String.format("alter table `%s`.`%s` drop column `%s`", schema, table, column);
        return sql;
    }

    public static String addNormalColumnSql(ColumnDefinition column, String schema, String table) {

        Assert.argument(StringUtils.hasText(column.getName()), () -> "column name is null");
        Assert.notNull(column.getTypes(), () -> "types is null");

        Types.ColumnType type = column.getTypes().getColumnType();
        String datatype;
        if (Types.ColumnType.VARCHAR.equals(type)) {
            datatype = String.format("VARCHAR(%s)", StringUtils.hasText(column.getTypes().getLength()) ? column.getTypes().getLength() : 500);
        } else {
            datatype = column.getTypes().getColumnType().name();
        }


        StringBuilder builder = new StringBuilder();
        builder.append(String.format("alter table `%s`.`%s` ", schema, table));
        builder.append(String.format("add `%s` %s ", column.getName(), datatype));

        boolean hasDefaultValue = StringUtils.hasText(column.getDefaultValue());
        if (hasDefaultValue) {
            builder.append(String.format("default %s ", column.getDefaultValue()));
        }
        if (column.isNotNull()) {
            builder.append("not null ");
        } else {
            builder.append("null ");
        }
        builder.append(String.format("comment '%s'", column.getComment()));

        return builder.toString();
    }

    public static String addAutoIncrementIdSql(ColumnDefinition column, String schema, String table) {
        Assert.state(Objects.equals("id", column.getName()), () -> "Auto-increment key is not matched, named 'id'", 400);
        Assert.state(column.isPrimaryKey(), () -> String.format("Column '%s' is not primary key", column.getName()), 400);
        Assert.state(column.isAutoIncrement(), () -> "Column 'id' is not auto increment", 400);

        Assert.notNull(column.getTypes(), () -> "types is null");
        Assert.state(Objects.equals(column.getTypes().getColumnType(), Types.ColumnType.INT), () -> "Auto-increment column id must be types of INT", 400);

        String sql = String.format("alter table `%s`.`%s` ", schema, table) +
                String.format("add `%s` %s not null comment '%s'", column.getName(), Types.ColumnType.INT, column.getComment());
        return sql;
    }

    public static String setAutoIncrementIdSql(ColumnDefinition column, String schema, String table) {
        return String.format("alter table `%s`.`%s` modify `%s` int(11) auto_increment", schema, table, column.getName());
    }

}
